package com.dingup.provider.service.classInfo.impl;

import com.alibaba.fastjson.JSONObject;
import com.dingup.api.Util.ClassRoomUtil;
import com.dingup.api.Util.DateUtil;
import com.dingup.api.adapter.student.StudentCourseInformationAdapter;
import com.dingup.api.bean.feign.paike.classInfo.PkClassInfoFeignBean;
import com.dingup.api.bean.page.PageData;
import com.dingup.api.bean.query.classInfo.ClassInfoForPkBean;
import com.dingup.api.bean.requestBean.classInfo.ClassInfoBean;
import com.dingup.api.bean.requestBean.classInfo.ClassPageBean;
import com.dingup.api.bean.response.SelectBean;
import com.dingup.api.enums.ClassStatusEnum;
import com.dingup.api.enums.ClassUserTypeEnum;
import com.dingup.api.enums.ExamTypeEnum;
import com.dingup.api.enums.StudentCampusEnum;
import com.dingup.api.model.classInfo.ClassInfo;
import com.dingup.api.model.classInfo.ClassUserInfo;
import com.dingup.api.model.lesson.LessonInfo;
import com.dingup.api.model.lesson.LessonSubjectInfo;
import com.dingup.api.model.student.StudentCourseInformation;
import com.dingup.api.model.sys.SysRole;
import com.dingup.api.model.sys.SysUser;
import com.dingup.provider.feign.client.paike.classInfo.PaikeClassInfoFeignClient;
import com.dingup.provider.mapper.*;
import com.dingup.provider.service.classInfo.ClassInfoService;
import com.dingup.provider.service.classInfo.ClassUserInfoService;
import com.dingup.provider.service.log.SysLogService;
import com.dingup.provider.service.student.StudentCourseService;
import com.dingup.provider.service.sys.SysDeptService;
import com.dingup.provider.service.sys.SysUserService;
import com.dingup.provider.util.PageDataUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by wancheng on 2018/8/24.
 */
@Service
public class ClassInfoServiceImpl implements ClassInfoService {

    private static Logger logger = LoggerFactory.getLogger(ClassInfoServiceImpl.class);

    @Autowired
    ClassInfoMapper classInfoMapper;
    @Autowired
    ClassUserInfoMapper classUserInfoMapper;
    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    SysRoleMapper sysRoleMapper;
    @Autowired
    SysDeptService sysDeptService;
    @Autowired
    SysUserService sysUserService;
    @Autowired
    LessonInfoMapper lessonInfoMapper;
    @Autowired
    SysLogService sysLogService;
    @Autowired
    ClassUserInfoService classUserInfoService;
    @Autowired
    StudentCourseInformationMapper courseInformationMapper;
    @Autowired
    StudentCourseService courseService;
    @Autowired
    PaikeClassInfoFeignClient paikeClassInfoFeignClient;
    @Autowired
    LessonSubjectInfoMapper lessonSubjectInfoMapper;

    @Override
    public PageData getClassInfo(ClassPageBean classPageBean, List<String> createUserIds) {
        PageHelper.startPage(classPageBean.getPage(), classPageBean.getRows());
        PageHelper.orderBy("create_time desc");
        List<ClassInfo> classInfos = classInfoMapper.getClassInfo(classPageBean, createUserIds);
        PageInfo<ClassInfo> pageInfo = new PageInfo<>(classInfos);
        formartData(pageInfo);
        return PageDataUtil.getPageData(pageInfo);
    }

    @Override
    public PageData getClassInfo(Integer page, Integer rows, String query, List<String> createUserIds) {
        PageHelper.startPage(page, rows);
        PageHelper.orderBy("create_time desc");
        List<ClassInfo> classInfos = classInfoMapper.getClassInfoByQuery(query, createUserIds);
        PageInfo<ClassInfo> pageInfo = new PageInfo<>(classInfos);
        formartData(pageInfo);
        return PageDataUtil.getPageData(pageInfo);
    }

    private void formartData(PageInfo<ClassInfo> pageInfo) {
        pageInfo.getList().forEach(
                classInfo -> {
                    LessonInfo lessonInfo = lessonInfoMapper.selectByPrimaryKey(classInfo.getLessonId());
                    if (lessonInfo != null) {
                        classInfo.setExam(ExamTypeEnum.getMap(lessonInfo.getExam()));
                        classInfo.setSchoolCampusMap(StudentCampusEnum.getMap(lessonInfo.getLessonCampus()));
                    }
                    List<ClassUserInfo> classTeahcers = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.CLASSTEACHER);
                    if (!CollectionUtils.isEmpty(classTeahcers)) {
                        classInfo.setClassTeacher(classTeahcers.get(0));
                    }

                    List<ClassUserInfo> students = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.STUDENT);
                    if (students != null) {
                        classInfo.setStudentNum(students.size());
                    } else {
                        classInfo.setStudentNum(0);
                    }
                    classInfo.setBeginTimeString(DateUtil.date2Str(classInfo.getBeginTime(), "yyyy/MM/dd"));
                    classInfo.setBeginTime(null);
                    classInfo.setEndTimeString(DateUtil.date2Str(classInfo.getEndTime(), "yyyy/MM/dd"));
                    classInfo.setEndTime(null);
                }

        );
    }

    @Override
    public ClassInfo getByClassName(String className) {
        return classInfoMapper.getByClassName(className);
    }

    @Override
    public List<SysUser> getTeacher(Long schoolCampusId, String roleName) {
        SysRole role = sysRoleMapper.getByRoleName(roleName);
        if (role == null) {
            return null;
        }
        List<Long> childs = sysDeptService.getChildDeptIds(schoolCampusId);
        List<SysUser> teachers = sysUserMapper.getUserByDeptAndRole(childs, role.getId());
        return teachers;
    }

    @Override
    public List<SysUser> getStudent(List<String> createUserIds) {
        return sysUserMapper.getStudentByCreateUserIds(createUserIds);
    }

    @Override
    @Transactional
    public ClassInfo saveClassInfo(ClassInfoBean classInfoBean) {
        logger.info("save class info , classInfo = {}", JSONObject.toJSONString(classInfoBean));
        ClassInfo classInfo = classInfoBean.getClassInfo();
        Date currentDate = new Date();
        if (currentDate.before(classInfo.getBeginTime())) {
            classInfo.setStatus(ClassStatusEnum.CLASS_UNSTART);
        } else if (currentDate.after(classInfo.getBeginTime()) && currentDate.before(classInfo.getEndTime())) {
            classInfo.setStatus(ClassStatusEnum.CLASS_IMPLEMENTING);
        } else if (currentDate.after(classInfo.getEndTime())) {
            classInfo.setStatus(ClassStatusEnum.CLASS_END);
        }
        classInfo.setIfDelete(false);
        classInfo.setCreateTime(currentDate);
        classInfoMapper.insertSelective(classInfo);
        List<ClassUserInfo> list = getClassInfoUserList(classInfoBean, classInfo);

        classUserInfoService.needInsert(list, classInfoBean.getCreateUserId(), classInfo.getId());

        //simpleClass 与 res 返回结果不一样
        paikeClassInfoFeignClient.addClassSyncEeo(classInfo);
        return classInfo;
    }

    public List<ClassUserInfo> getClassInfoUserList(ClassInfoBean classInfoBean, ClassInfo classInfo) {
        Date currentDate = new Date();
        String classTeacherId = classInfoBean.getClassTeacherId();
        String[] teacherIds = classInfoBean.getTeacherIds();
        String[] studentIds = classInfoBean.getStudentIds();
        List<ClassUserInfo> list = new ArrayList<>();
        ClassUserInfo classUserInfo = new ClassUserInfo();
        classUserInfo.setCreateUserId(classInfoBean.getCreateUserId());
        classUserInfo.setClassId(classInfo.getId());
        classUserInfo.setCreateTime(currentDate);
        if (!StringUtils.isEmpty(classTeacherId)) {
            ClassUserInfo classTeacherInfo = null;
            try {
                classTeacherInfo = classUserInfo.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            classTeacherInfo.setUserId(classTeacherId);
            classTeacherInfo.setUserName(sysUserMapper.selectByPrimaryKey(classTeacherId).getUserName());
            classTeacherInfo.setType(ClassUserTypeEnum.CLASSTEACHER);
            list.add(classTeacherInfo);
        }
        if (teacherIds != null && teacherIds.length > 0) {
            Arrays.stream(teacherIds).forEach(
                    t -> {
                        ClassUserInfo teacherInfo = null;
                        try {
                            teacherInfo = classUserInfo.clone();
                            teacherInfo.setUserId(t);
                            teacherInfo.setUserName(sysUserMapper.selectByPrimaryKey(t).getUserName());
                            teacherInfo.setType(ClassUserTypeEnum.TEACHER);
                            list.add(teacherInfo);
                        } catch (CloneNotSupportedException e) {
                            e.printStackTrace();
                        }
                    }
            );
        }
        if (studentIds != null && studentIds.length > 0) {
            Arrays.stream(studentIds).forEach(
                    s -> {
                        ClassUserInfo studentInfo = null;
                        try {
                            studentInfo = classUserInfo.clone();
                            studentInfo.setUserId(s);
                            studentInfo.setUserName(sysUserMapper.selectByPrimaryKey(s).getUserName());
                            studentInfo.setType(ClassUserTypeEnum.STUDENT);
                            list.add(studentInfo);
                        } catch (CloneNotSupportedException e) {
                            e.printStackTrace();
                        }
                    }
            );
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateClassInfo(ClassInfoBean classInfoBean, String operaUserId) throws CloneNotSupportedException {
        logger.info("update class info , classInfo = {}", JSONObject.toJSONString(classInfoBean));
        ClassInfo oldClass = getClassInfo(classInfoBean.getId());
        ClassInfo classInfo = classInfoBean.getClassInfo();
        classInfo.setOperaUserId(operaUserId);
        Date currentDate = new Date();
        if (currentDate.before(classInfo.getBeginTime())) {
            classInfo.setStatus(ClassStatusEnum.CLASS_UNSTART);
        } else if (currentDate.after(classInfo.getBeginTime()) && currentDate.before(classInfo.getEndTime())) {
            classInfo.setStatus(ClassStatusEnum.CLASS_IMPLEMENTING);
        } else if (currentDate.after(classInfo.getEndTime())) {
            classInfo.setStatus(ClassStatusEnum.CLASS_END);
        }
        classInfoMapper.updateByPrimaryKeySelective(classInfo);
        List<ClassUserInfo> list = getClassInfoUserList(classInfoBean, classInfo);
        List<ClassUserInfo> older = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), null);

        List<ClassUserInfo> needInsert = list.stream().filter(item -> !older.contains(item)).collect(Collectors.toList());
        List<ClassUserInfo> needDelete = older.stream().filter(item -> !list.contains(item)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(needDelete)) {
            classUserInfoService.needDelete(needDelete, operaUserId, classInfoBean.getId());
        }
        if (!CollectionUtils.isEmpty(needInsert)) {
            classUserInfoService.needInsert(needInsert, operaUserId, classInfoBean.getId());
        }
        paikeClassInfoFeignClient.updateClassSyncEeo(new PkClassInfoFeignBean(oldClass, classInfo));
    }

    @Override
    public ClassInfo getClassInfo(Integer classId) {
        ClassInfo classInfo = classInfoMapper.selectByPrimaryKey(classId);
        if (classInfo != null) {
            formartClassInfo(classInfo);
        }
        return classInfo;
    }

    private void formartClassInfo(ClassInfo classInfo) {
        LessonInfo lesson = lessonInfoMapper.selectByPrimaryKey(classInfo.getLessonId());
        if (lesson != null) {
            classInfo.setLessonName(lesson.getLessonName());
            classInfo.setExam(ExamTypeEnum.getMap(lesson.getExam()));
            classInfo.setSchoolCampusMap(StudentCampusEnum.getMap(lesson.getLessonCampus()));
            classInfo.setCampusRooms(ClassRoomUtil.getCampusRooms(StudentCampusEnum.getEnum(lesson.getLessonCampus())));
            List<LessonSubjectInfo> subjectInfos = lessonSubjectInfoMapper.getByLessonId(lesson.getId());
            if (!CollectionUtils.isEmpty(subjectInfos)) {
                classInfo.setLessonSubjectInfos(subjectInfos.stream().map(s -> new SelectBean(s.getNameCh(), s.getNameCh())).collect(Collectors.toList()));
            }
        }
        List<ClassUserInfo> classTeachers = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.CLASSTEACHER);
        if (!CollectionUtils.isEmpty(classTeachers)) {
            classInfo.setClassTeacher(classTeachers.get(0));
        }
        List<ClassUserInfo> teachers = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.TEACHER);
        List<ClassUserInfo> students = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.STUDENT);
        classInfo.setTeachers(teachers);
        classInfo.setStudents(students);
        classInfo.setStudentNum(students.size());
        classInfo.setBeginTimeString(DateUtil.date2Str(classInfo.getBeginTime(), "yyyy.MM.dd"));
        classInfo.setEndTimeString(DateUtil.date2Str(classInfo.getEndTime(), "yyyy.MM.dd"));
    }

    @Override
    public PageData getClassInfoByLessonIdAndStatus(Integer page, Integer rows, Integer lessonId, ClassStatusEnum classStatusEnum) {
        PageHelper.startPage(page, rows);
        List<ClassInfo> classInfos = classInfoMapper.getClassInfoByLessonIdAndStatus(lessonId, classStatusEnum);

        PageInfo<ClassInfo> pageInfo = new PageInfo<>(classInfos);
        formartClassInfo(pageInfo.getList());
        List<Integer> classIds = classInfos.stream().map(ClassInfo::getId).collect(Collectors.toList());
        Integer studentCount = 0;
        if (!CollectionUtils.isEmpty(classIds)) {
            studentCount = classUserInfoMapper.getCountByClassIdsAndType(classIds, ClassUserTypeEnum.STUDENT);
        }
        Map<String, Object> res = new HashMap<>();
        res.put("classCount", pageInfo.getTotal());
        res.put("studentCount", studentCount);
        //课程下未分班的学生
        Integer studentUnDivideCount = 0;
        studentUnDivideCount = courseInformationMapper.getStudentUnDivideCount(lessonId);
        res.put("studentUnDivideCount",studentUnDivideCount);
        PageData pageData = PageDataUtil.getPageData(pageInfo);
        pageData.setOtherMsg(res);
        return pageData;
    }
    private void formartClassInfo(List<ClassInfo> classInfos){
        classInfos.forEach(
                classInfo -> {
                    List<ClassUserInfo> classTeachers = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.CLASSTEACHER);
                    if (!CollectionUtils.isEmpty(classTeachers)) {
                        classInfo.setClassTeacher(classTeachers.get(0));
                    }

                    List<ClassUserInfo> students = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.STUDENT);
                    if (students != null) {
                        classInfo.setStudentNum(students.size());
                    }
                    classInfo.setStudents(students);
                    classInfo.setBeginTimeString(DateUtil.date2Str(classInfo.getBeginTime(), "yyyy.MM.dd"));
                    classInfo.setBeginTime(null);
                    classInfo.setEndTimeString(DateUtil.date2Str(classInfo.getEndTime(), "yyyy.MM.dd"));
                    classInfo.setEndTime(null);
                }
        );
    }
    @Override
    public void updateClassStatus(Integer classId, ClassStatusEnum classStatusEnum, String operaUserId) {
        ClassInfo classInfo = classInfoMapper.selectByPrimaryKey(classId);
        classInfo.setStatus(classStatusEnum);
        Date currentDate = DateUtil.formatDate(new Date());
        classInfo.setEndTime(currentDate);
        if (classInfo.getBeginTime().after(currentDate)) {
            classInfo.setBeginTime(currentDate);
        }
        classInfoMapper.updateByPrimaryKeySelective(classInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteClass(Integer classId, String operaUserId) {
        ClassInfo classInfo = getClassInfo(classId);
        classInfo.setId(classId);
        classInfo.setIfDelete(true);
        classInfoMapper.updateByPrimaryKeySelective(classInfo);
        classUserInfoService.needDelete(classInfo.getStudents(), operaUserId, classId);
        paikeClassInfoFeignClient.deleteClassSyncEeo(classId);
    }

    @Override
    public List<ClassInfo> getClassByLessonId(Integer lessonId) {
        List<ClassInfo> classInfos = classInfoMapper.getClassByLessonId(lessonId);
        classInfos.forEach(
                classInfo -> {
                    List<ClassUserInfo> classTeachers = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.CLASSTEACHER);
                    if (!CollectionUtils.isEmpty(classTeachers)) {
                        classInfo.setClassTeacher(classTeachers.get(0));
                    }
                    List<ClassUserInfo> students = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.STUDENT);
                    if (students != null) {
                        classInfo.setStudentNum(students.size());
                    }
                    classInfo.setBeginTimeString(DateUtil.date2Str(classInfo.getBeginTime(), "yyyy.MM.dd"));
                    classInfo.setBeginTime(null);
                    classInfo.setEndTimeString(DateUtil.date2Str(classInfo.getEndTime(), "yyyy.MM.dd"));
                    classInfo.setEndTime(null);
                }
        );
        return classInfos;
    }

    @Override
    public List<ClassInfo> getClassByLessonIdAndUserId(Integer lessonId, String userId) {
        List<ClassInfo> classInfos = classInfoMapper.getByLessonIdAndUserId(lessonId, userId, null);
        return classInfos;
    }

    @Override
    public ClassInfo getCourseClassInfo(Integer classId) {
        ClassInfo classInfo = classInfoMapper.selectByPrimaryKey(classId);
        List<ClassUserInfo> classTeachers = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.CLASSTEACHER);
        if (!CollectionUtils.isEmpty(classTeachers)) {
            classInfo.setClassTeacher(classTeachers.get(0));
        }
        List<ClassUserInfo> students = classUserInfoMapper.getClassUserInfoByClassAndType(classInfo.getId(), ClassUserTypeEnum.STUDENT);
        if (students != null) {
            classInfo.setStudentNum(students.size());
        }
        classInfo.setBeginTimeString(DateUtil.date2Str(classInfo.getBeginTime(), "yyyy.MM.dd"));
        classInfo.setBeginTime(null);
        classInfo.setEndTimeString(DateUtil.date2Str(classInfo.getEndTime(), "yyyy.MM.dd"));
        classInfo.setEndTime(null);
        return classInfo;
    }

    @Override
    public List<StudentCourseInformationAdapter> getUnDivideStudentByLessonId(Integer lessonId) {
        return courseInformationMapper.getStudentUnDivide(lessonId);
    }

    @Override
    public void divideStudent(Integer courseId, Integer classId,String divideUserId) {
        StudentCourseInformation course = courseInformationMapper.selectByPrimaryKey(courseId);
        course.setClassId(classId);
        courseService.updateStudentCourse(course,divideUserId);
    }

    @Override
    public List<ClassInfo> getClassInfo(ClassInfoForPkBean bean) {
        List<ClassInfo> res = classInfoMapper.getClassInfoForPK(bean);
        res.forEach(
                c->{
                    c.setSchoolCampusMap(StudentCampusEnum.getMap(c.getSchoolCampus()));
                    c.setExam(ExamTypeEnum.getMap(c.getExamString()));
                }
        );
        return res;
    }

    @Override
    public List<ClassInfo> getAllClassInfo() {
        List<ClassInfo> list = classInfoMapper.getAllClassInfoUnDelete();
        return list;
    }

    @Override
    public List<Map<String, Object>> getClassInfoGroupByTeacherSelf(String teacherId) {
        List<ClassInfo> self = classInfoMapper.getClassInfoByTeacherId(teacherId, ClassUserTypeEnum.TEACHER);
        List<Integer> selfClassIds = self.stream().map(ClassInfo::getId).collect(Collectors.toList());
        List<ClassInfo> other = classInfoMapper.getClassInfoNorIn(selfClassIds);
        List<Map<String, Object>> res = new ArrayList<>();
        List<SelectBean> selfSelectBean = self.stream().map(c -> new SelectBean(c.getClassName(), c.getId())).collect(Collectors.toList());
        List<SelectBean> otherSelectBean = other.stream().map(c -> new SelectBean(c.getClassName(), c.getId())).collect(Collectors.toList());
        Map<String, Object> selfMap = new HashMap<>();
        selfMap.put("label", "你负责的班级");
        selfMap.put("options", selfSelectBean);
        res.add(selfMap);
        Map<String, Object> otherMap = new HashMap<>();
        otherMap.put("label", "其他班级");
        otherMap.put("options", otherSelectBean);
        res.add(otherMap);
        return res;
    }

}
